package com.mathpractise.service.impl;

import com.mathpractise.dto.response.StatisticsReportDTO;
import com.mathpractise.model.AnswerDetail;
import com.mathpractise.model.StatisticsReport;
import com.mathpractise.model.TrainingSession;
import com.mathpractise.repository.StatisticsRepository;
import com.mathpractise.repository.TrainingRepository;
import com.mathpractise.service.StatisticsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * 统计服务实现类
 */
@Service
public class StatisticsServiceImpl implements StatisticsService {
    
    private static final Logger logger = LoggerFactory.getLogger(StatisticsServiceImpl.class);
    
    @Autowired
    private TrainingRepository trainingRepository;
    
    @Autowired
    private StatisticsRepository statisticsRepository;
    
    @Override
    public StatisticsReportDTO getSessionStatistics(String sessionId) {
        logger.info("获取会话统计信息: sessionId={}", sessionId);
        
        // 先从缓存/文件中查找统计报告
        Optional<StatisticsReport> reportOptional = statisticsRepository.findBySessionId(sessionId);
        if (reportOptional.isPresent()) {
            logger.info("从缓存中获取统计信息: sessionId={}", sessionId);
            return convertToDTO(reportOptional.get());
        }
        
        // 如果没有找到，则生成统计报告
        logger.info("缓存中未找到统计信息，重新生成: sessionId={}", sessionId);
        return generateStatisticsReport(sessionId);
    }
    
    @Override
    public StatisticsReportDTO generateStatisticsReport(String sessionId) {
        logger.info("生成统计报告: sessionId={}", sessionId);
        
        // 获取训练会话
        Optional<TrainingSession> sessionOptional = trainingRepository.findById(sessionId);
        if (!sessionOptional.isPresent()) {
            logger.error("未找到训练会话: {}", sessionId);
            throw new RuntimeException("Training session not found: " + sessionId);
        }
        
        TrainingSession session = sessionOptional.get();
        
        // 创建统计报告
        StatisticsReport report = new StatisticsReport();
        report.setSessionId(sessionId);
        
        List<AnswerDetail> answerDetails = session.getAnswerDetails();
        if (answerDetails == null) {
            answerDetails = new ArrayList<>();
        }
        
        // 计算完成题目数量
        int completedQuestions = answerDetails.size();
        report.setCompletedQuestions(completedQuestions);
        logger.info("完成题目数量: {}, sessionId={}", completedQuestions, sessionId);
        
        // 计算正确率
        long correctCount = answerDetails.stream()
                .mapToLong(detail -> detail.getCorrect() != null && detail.getCorrect() ? 1 : 0)
                .sum();
        
        double accuracyRate = completedQuestions > 0 ? (double) correctCount / completedQuestions * 100 : 0;
        report.setAccuracyRate(accuracyRate);
        logger.info("正确率计算完成: {}%, sessionId={}", accuracyRate, sessionId);
        
        // 计算平均用时
        if (!answerDetails.isEmpty()) {
            double averageTimeSpent = answerDetails.stream()
                    .mapToLong(AnswerDetail::getTimeSpent)
                    .average()
                    .orElse(0.0);
            report.setAverageTimeSpent(averageTimeSpent);
            logger.info("平均用时计算完成: {}秒, sessionId={}", averageTimeSpent, sessionId);
        }
        
        // 计算错误题目列表
        List<AnswerDetail> wrongAnswers = new ArrayList<>();
        for (AnswerDetail detail : answerDetails) {
            if (detail.getCorrect() == null || !detail.getCorrect()) {
                wrongAnswers.add(detail);
            }
        }
        report.setWrongAnswers(wrongAnswers);
        logger.info("错误题目统计完成: {}题, sessionId={}", wrongAnswers.size(), sessionId);
        
        // TODO: 计算耗时长尾分析（找出耗时明显过高的题目）
        report.setTimeConsumingOutliers(new ArrayList<>());
        
        // 保存统计报告
        statisticsRepository.save(report);
        logger.info("统计报告保存完成: sessionId={}", sessionId);
        
        // 转换为DTO并返回
        StatisticsReportDTO dto = convertToDTO(report);
        logger.info("统计报告生成完成: sessionId={}", sessionId);
        return dto;
    }
    
    @Override
    public String deleteHistoryStatistics(String beforeDate) {
        logger.info("删除历史统计数据: beforeDate={}", beforeDate);
        
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse(beforeDate);
            statisticsRepository.deleteBeforeDate(date);
            logger.info("历史统计数据删除成功: beforeDate={}", beforeDate);
            return "Successfully deleted history statistics before " + beforeDate;
        } catch (ParseException e) {
            logger.error("日期格式错误: {}", beforeDate, e);
            throw new RuntimeException("Invalid date format. Please use yyyy-MM-dd format.", e);
        }
    }
    
    @Override
    public String exportToCsv(String sessionId) {
        logger.info("导出CSV数据: sessionId={}", sessionId);
        
        StatisticsReportDTO report = getSessionStatistics(sessionId);
        
        StringWriter writer = new StringWriter();
        
        // Write header
        writer.append("指标,数值\n");
        writer.append("总题数,").append(String.valueOf(report.getTotalQuestions())).append("\n");
        writer.append("正确题数,").append(String.valueOf(report.getCorrectAnswers())).append("\n");
        writer.append("正确率,").append(String.format("%.2f", report.getAccuracyRate())).append("%\n");
        writer.append("平均用时(秒),").append(String.valueOf(report.getAverageTimeSpent())).append("\n");
        writer.append("错误题数,").append(String.valueOf(report.getWrongAnswers().size())).append("\n");
        
        // Write wrong answers section
        writer.append("\n错误题目详情:\n");
        writer.append("题目ID,用户答案,用时(秒),答题时间\n");
        for (AnswerDetail detail : report.getWrongAnswers()) {
            writer.append(detail.getQuestionId()).append(",")
                  .append(String.valueOf(detail.getUserAnswer())).append(",")
                  .append(String.valueOf(detail.getTimeSpent())).append(",")
                  .append(detail.getAnswerTime().toString()).append("\n");
        }
        
        logger.info("CSV数据导出完成: sessionId={}", sessionId);
        return writer.toString();
    }
    
    private StatisticsReportDTO convertToDTO(StatisticsReport report) {
        StatisticsReportDTO dto = new StatisticsReportDTO();
        dto.setSessionId(report.getSessionId());
        dto.setCompletedQuestions(report.getCompletedQuestions() != null ? report.getCompletedQuestions() : 0);
        dto.setTotalQuestions(report.getCompletedQuestions() != null ? report.getCompletedQuestions() : 0);
        dto.setCorrectAnswers(report.getAccuracyRate() != null ?
                (int) Math.round(report.getAccuracyRate() / 100 * report.getCompletedQuestions()) : 0);
        dto.setAccuracyRate(report.getAccuracyRate() != null ? report.getAccuracyRate() : 0.0);
        dto.setAverageTimeSpent(report.getAverageTimeSpent() != null ? 
                Math.round(report.getAverageTimeSpent()) : 0L);
        dto.setWrongAnswers(report.getWrongAnswers() != null ? report.getWrongAnswers() : new ArrayList<>());
        dto.setTimeConsumingOutliers(report.getTimeConsumingOutliers() != null ? 
                report.getTimeConsumingOutliers() : new ArrayList<>());
        
        return dto;
    }
}